{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#|default_exp callback.PredictionDynamics"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# PredictionDynamics"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    ">Callback used to visualize model predictions during training.\n",
    "\n",
    "This is an implementation created by Ignacio Oguiza (oguiza@timeseriesAI.co) based on a [blog post](http://localhost:8888/?token=83bca9180c34e1c8991886445942499ee8c1e003bc0491d0) by Andrej Karpathy I read some time ago that I really liked. One of the things he mentioned was this: \n",
    "\n",
    ">\"**visualize prediction dynamics**. I like to visualize model predictions on a fixed test batch during the course of training. The “dynamics” of how these predictions move will give you incredibly good intuition for how the training progresses. Many times it is possible to feel the network “struggle” to fit your data if it wiggles too much in some way, revealing instabilities. Very low or very high learning rates are also easily noticeable in the amount of jitter.\" A. Karpathy\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "from fastai.callback.all import *\n",
    "from tsai.imports import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#|export\n",
    "class PredictionDynamics(Callback):\n",
    "    order, run_valid = 65, True\n",
    "\n",
    "    def __init__(self, show_perc=1., figsize=(10,6), alpha=.3, size=30, color='lime', cmap='gist_rainbow', normalize=False, \n",
    "                 sensitivity=None, specificity=None):\n",
    "\n",
    "        \"\"\"\n",
    "        Args:\n",
    "            show_perc:   percent of samples from the valid set that will be displayed. Default: 1 (all).\n",
    "                         You can reduce it if the number is too high and the chart is too busy.\n",
    "            alpha:       level of transparency. Default:.3. 1 means no transparency.\n",
    "            figsize:     size of the chart. You may want to expand it if too many classes.\n",
    "            size:        size of each sample in the chart. Default:30. You may need to decrease it a bit if too many classes/ samples.\n",
    "            color:       color used in regression plots.\n",
    "            cmap:        color map used in classification plots.\n",
    "            normalize:   flag to normalize histograms displayed in binary classification.\n",
    "            sensitivity: (aka recall or True Positive Rate) if you pass a float between 0. and 1. the sensitivity threshold will be plotted in the chart.\n",
    "                         Only used in binary classification.\n",
    "            specificity: (or True Negative Rate) if you pass a float between 0. and 1. it will be plotted in the chart. Only used in binary classification.\n",
    "\n",
    "        The red line in classification tasks indicate the average probability of true class.\n",
    "        \"\"\"\n",
    "\n",
    "        store_attr()\n",
    "\n",
    "    def before_fit(self):\n",
    "        self.run = not hasattr(self.learn, 'lr_finder') and not hasattr(self, \"gather_preds\")\n",
    "        if not self.run:\n",
    "            return\n",
    "        self.cat = True if (hasattr(self.dls, \"c\") and self.dls.c > 1) else False\n",
    "        if self.cat:\n",
    "            self.binary = self.dls.c == 2\n",
    "        if self.show_perc != 1:\n",
    "            valid_size = len(self.dls.valid.dataset)\n",
    "            self.show_idxs = random_choice(valid_size, int(round(self.show_perc * valid_size)), replace=False)\n",
    "\n",
    "        # Prepare ground truth container\n",
    "        self.y_true = []\n",
    "\n",
    "    def before_epoch(self):\n",
    "        # Prepare empty pred container in every epoch\n",
    "        self.y_pred = []\n",
    "\n",
    "    def after_pred(self):\n",
    "        if self.training:\n",
    "            return\n",
    "\n",
    "        # Get y_true in epoch 0\n",
    "        if self.epoch == 0:\n",
    "            self.y_true.extend(self.y.cpu().flatten().numpy())\n",
    "\n",
    "        # Gather y_pred for every batch\n",
    "        if self.cat:\n",
    "            if self.binary:\n",
    "                y_pred = F.softmax(self.pred, -1)[:, 1].reshape(-1, 1).cpu()\n",
    "            else:\n",
    "                y_pred = torch.gather(F.softmax(self.pred, -1), -1, self.y.reshape(-1, 1).long()).cpu()\n",
    "        else:\n",
    "            y_pred = self.pred.cpu()\n",
    "        self.y_pred.extend(y_pred.flatten().numpy())\n",
    "\n",
    "    def after_epoch(self):\n",
    "        # Ground truth\n",
    "        if self.epoch == 0:\n",
    "            self.y_true = np.array(self.y_true)\n",
    "            if self.show_perc != 1:\n",
    "                self.y_true = self.y_true[self.show_idxs]\n",
    "            self.y_bounds = (np.min(self.y_true), np.max(self.y_true))\n",
    "            self.min_x_bounds, self.max_x_bounds = np.min(self.y_true), np.max(self.y_true)\n",
    "\n",
    "        self.y_pred = np.array(self.y_pred)\n",
    "        if self.show_perc != 1:\n",
    "            self.y_pred = self.y_pred[self.show_idxs]\n",
    "        if self.cat:\n",
    "            neg_thr = None\n",
    "            pos_thr = None\n",
    "            if self.specificity is not None: \n",
    "                inp0 = self.y_pred[self.y_true == 0]\n",
    "                neg_thr = np.sort(inp0)[-int(len(inp0) * (1 - self.specificity))]\n",
    "            if self.sensitivity is not None: \n",
    "                inp1 = self.y_pred[self.y_true == 1]\n",
    "                pos_thr = np.sort(inp1)[-int(len(inp1) * self.sensitivity)]\n",
    "            self.update_graph(self.y_pred, self.y_true, neg_thr=neg_thr, pos_thr=pos_thr)\n",
    "        else:\n",
    "            # Adjust bounds during validation\n",
    "            self.min_x_bounds = min(self.min_x_bounds, np.min(self.y_pred))\n",
    "            self.max_x_bounds = max(self.max_x_bounds, np.max(self.y_pred))\n",
    "            x_bounds = (self.min_x_bounds, self.max_x_bounds)\n",
    "            self.update_graph(self.y_pred, self.y_true, x_bounds=x_bounds, y_bounds=self.y_bounds)\n",
    "\n",
    "    def update_graph(self, y_pred, y_true, x_bounds=None, y_bounds=None, neg_thr=None, pos_thr=None):\n",
    "        if not hasattr(self, 'graph_fig'):\n",
    "            self.df_out = display(\"\", display_id=True)\n",
    "            if self.cat:\n",
    "                self._cl_names = self.dls.vocab\n",
    "                self._classes = L(self.dls.vocab.o2i.values())\n",
    "                self._n_classes = len(self._classes)\n",
    "                if self.binary:\n",
    "                    self.bins = np.linspace(0, 1, 101)\n",
    "                else:\n",
    "                    _cm = plt.get_cmap(self.cmap)\n",
    "                    self._color = [_cm(1. * c/self._n_classes) for c in range(1, self._n_classes + 1)][::-1]\n",
    "                    self._h_vals = np.linspace(-.5, self._n_classes - .5, self._n_classes + 1)[::-1]\n",
    "                    self._rand = []\n",
    "                    for i, c in enumerate(self._classes):\n",
    "                        self._rand.append(.5 * (np.random.rand(np.sum(y_true == c)) - .5))\n",
    "            self.graph_fig, self.graph_ax = plt.subplots(1, figsize=self.figsize)\n",
    "            self.graph_out = display(\"\", display_id=True)\n",
    "        self.graph_ax.clear()\n",
    "        if self.cat:\n",
    "            if self.binary:\n",
    "                self.graph_ax.hist(y_pred[y_true == 0], bins=self.bins, density=self.normalize,  color='red', label=self._cl_names[0],\n",
    "                                          edgecolor='black', alpha=self.alpha)\n",
    "                self.graph_ax.hist(y_pred[y_true == 1], bins=self.bins, density=self.normalize,  color='blue', label=self._cl_names[1],\n",
    "                                          edgecolor='black', alpha=self.alpha)\n",
    "                self.graph_ax.axvline(.5, lw=1, ls='--', color='gray')\n",
    "                if neg_thr is not None: \n",
    "                    self.graph_ax.axvline(neg_thr, lw=2, ls='--', color='red', label=f'specificity={(self.specificity):.3f}')\n",
    "                if pos_thr is not None: \n",
    "                    self.graph_ax.axvline(pos_thr, lw=2, ls='--', color='blue', label=f'sensitivity={self.sensitivity:.3f}')\n",
    "                self.graph_ax.set_xlabel(f'probability of class {self._cl_names[1]}', fontsize=12)\n",
    "                self.graph_ax.legend()\n",
    "            else:\n",
    "                for i, c in enumerate(self._classes):\n",
    "                    self.graph_ax.scatter(y_pred[y_true == c], y_true[y_true == c] + self._rand[i],  color=self._color[i],\n",
    "                                          edgecolor='black', alpha=self.alpha, lw=.5, s=self.size)\n",
    "                    self.graph_ax.vlines(np.mean(y_pred[y_true == c]), i - .5, i + .5, color='r')\n",
    "                self.graph_ax.vlines(.5, min(self._h_vals), max(self._h_vals), lw=.5)\n",
    "                self.graph_ax.hlines(self._h_vals, 0, 1, lw=.5)\n",
    "                self.graph_ax.set_ylim(min(self._h_vals), max(self._h_vals))\n",
    "                self.graph_ax.set_yticks(self._classes)\n",
    "                self.graph_ax.set_yticklabels(self._cl_names)\n",
    "                self.graph_ax.set_ylabel('true class', fontsize=12)\n",
    "                self.graph_ax.set_xlabel('probability of true class', fontsize=12)\n",
    "            self.graph_ax.set_xlim(0, 1)\n",
    "            self.graph_ax.set_xticks(np.linspace(0, 1, 11))\n",
    "            self.graph_ax.grid(axis='x', color='gainsboro', lw=.2)\n",
    "        else:\n",
    "            self.graph_ax.scatter(y_pred, y_true, color=self.color, edgecolor='black', alpha=self.alpha, lw=.5, s=self.size)\n",
    "            self.graph_ax.set_xlim(*x_bounds)\n",
    "            self.graph_ax.set_ylim(*y_bounds)\n",
    "            self.graph_ax.plot([*x_bounds], [*x_bounds], color='gainsboro')\n",
    "            self.graph_ax.set_xlabel('y_pred', fontsize=12)\n",
    "            self.graph_ax.set_ylabel('y_true', fontsize=12)\n",
    "            self.graph_ax.grid(color='gainsboro', lw=.2)\n",
    "        self.graph_ax.set_title(f'Prediction Dynamics \\nepoch: {self.epoch + 1}/{self.n_epoch}')\n",
    "        self.df_out.update(pd.DataFrame(np.stack(self.learn.recorder.values)[-1].reshape(1,-1),\n",
    "                                        columns=self.learn.recorder.metric_names[1:-1], index=[self.epoch]))\n",
    "        self.graph_out.update(self.graph_ax.figure)\n",
    "        if self.epoch == self.n_epoch - 1: \n",
    "            plt.close(self.graph_ax.figure)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tsai.basics import *\n",
    "from tsai.models.InceptionTime import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "X      - shape: [360 samples x 24 features x 51 timesteps]  type: memmap  dtype:float32  isnan: 0\n",
      "y      - shape: (360,)  type: memmap  dtype:<U3  n_classes: 6 (60 samples per class) ['1.0', '2.0', '3.0', '4.0', '5.0', '6.0']  isnan: False\n",
      "splits - n_splits: 2 shape: [180, 180]  overlap: False\n"
     ]
    }
   ],
   "source": [
    "dsid = 'NATOPS'\n",
    "X, y, splits = get_UCR_data(dsid, split_data=False)\n",
    "check_data(X, y, splits, False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: left;\">\n",
       "      <th>epoch</th>\n",
       "      <th>train_loss</th>\n",
       "      <th>valid_loss</th>\n",
       "      <th>accuracy</th>\n",
       "      <th>time</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>0</td>\n",
       "      <td>1.885462</td>\n",
       "      <td>1.773872</td>\n",
       "      <td>0.238889</td>\n",
       "      <td>00:05</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>1</td>\n",
       "      <td>1.425667</td>\n",
       "      <td>1.640418</td>\n",
       "      <td>0.377778</td>\n",
       "      <td>00:05</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>train_loss</th>\n",
       "      <th>valid_loss</th>\n",
       "      <th>accuracy</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1.425667</td>\n",
       "      <td>1.640418</td>\n",
       "      <td>0.377778</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   train_loss  valid_loss  accuracy\n",
       "1    1.425667    1.640418  0.377778"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 720x432 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "tfms  = [None, [Categorize()]]\n",
    "batch_tfms = [TSStandardize(by_var=True)]\n",
    "dls = get_ts_dls(X, y, splits=splits, tfms=tfms, batch_tfms=batch_tfms)\n",
    "learn = ts_learner(dls, InceptionTime, metrics=accuracy, cbs=PredictionDynamics()) \n",
    "learn.fit_one_cycle(2, 3e-3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": "IPython.notebook.save_checkpoint();",
      "text/plain": [
       "<IPython.core.display.Javascript object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/Users/nacho/notebooks/tsai/nbs/064_callback.PredictionDynamics.ipynb saved at 2022-11-09 12:59:36\n",
      "Correct notebook to script conversion! 😃\n",
      "Wednesday 09/11/22 12:59:39 CET\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "                <audio  controls=\"controls\" autoplay=\"autoplay\">\n",
       "                    <source src=\"data:audio/wav;base64,UklGRvQHAABXQVZFZm10IBAAAAABAAEAECcAACBOAAACABAAZGF0YdAHAAAAAPF/iPh/gOoOon6w6ayCoR2ZeyfbjobxK+F2Hs0XjKc5i3DGvzaTlEaraE+zz5uLUl9f46fHpWJdxVSrnfmw8mYEScqUP70cb0Q8X41uysJ1si6Eh1jYzXp9IE2DzOYsftYRyoCY9dJ/8QICgIcEun8D9PmAaBPlfT7lq4MFIlh61tYPiCswIHX+yBaOqT1QbuW7qpVQSv9lu6+xnvRVSlyopAypbGBTUdSalrSTaUBFYpInwUpxOzhti5TOdndyKhCGrdwAfBUcXIJB69p+Vw1egB76+n9q/h6ADglbf4LvnIHfF/981ODThF4m8HiS0riJVjQ6c+/EOZCYQfJrGrhBmPVNMmNArLKhQlkXWYqhbaxXY8ZNHphLuBJsZUEckCTFVHMgNKGJytIDeSUmw4QN4Qx9pReTgb3vYX/TCBuApf75f+P5Y4CRDdN+B+tngk8c8nt03CKGqipgd13OhotwOC5x9MCAknFFcmlmtPmagFFFYOCo0qRzXMhVi57pryNmIEqJlRi8bm52PfuNM8k4dfQv+4cO12l6zCGdg3jl730uE/KAPvS+f0wEAoAsA89/XfXQgBESIn6S5luDtiC8eh/YmIfpLqt1OMp5jXg8/24MveqUNUnPZsqw0Z3yVDldnaUOqIZfXlKrm36zzWhjRhaT+r+ncHI5/otUzfd2uSt7hl/bqXtoHaCC6+mqfrAOeoDD+PJ/xf8RgLMHfH/b8GeBihZIfSXidoQSJWB52NM1iRkzz3MkxpKPbUCrbDu5d5fgTAxkSK3JoEhYD1p2omere2LZTuqYLbdWa49Cx5Dww7tyXDUnioXRkHhwJyKFvd/AfPoYy4Fl7j1/LQorgEr9/X89+0qAOAwAf13sJoL8Gkd8wt25hWIp3Heez/eKODfPcSPCzpFNRDVqf7UlmnNQKGHgqd+jgVvJVm2f265QZTpLS5byur1tpT6ajvrHq3Q2MXWIxtUCehoj8YMk5LB9hRQegeTypn+nBQWA0QHgf7f2q4C5EFt+5ucOg2YfHXtq2SSHpS0ydnTL4IxFO6pvNb4ulBdInWfcsfSc7VMmXpSmE6eeXmZThJxpsgRohEfOk86+AHCoOpOMFsx1dv8s6oYT2k17uR7ngpXod34IEJqAaPfnfyABCIBZBpl/NPI2gTQVjX134x2ExSPMeR7VtYjZMWJ0W8ftjkA/YW1durCWykvjZFKu4p9LVwVbZKNkqpxh6U+6mRC2mGq2Q3SRvsIgcpc2sIpD0Bp4uiiFhW3ecXxOGgaCDe0Vf4cLPoDv+/5/mfw1gN4KKX+17emBqBmYfBHfVYUZKFR44NBtiv41bHJUwx+RJkP1apu2VJlkTwli4qrwoo1ax1dToNCtemRSTBGXz7kJbdM/PY/Dxht0dTLziH7Ul3loJEiE0uJsfdsVTYGL8Yt/AgcMgHYA7X8S+IqAYA+QfjzpxIIVHnp7tdqzhmAstXaxzEqMETpScGC/dJP3Rmdo8LIZnOVSEF+Opxumsl1sVF+dVrE5Z6NIiZSkvVdv2zsqjdnK8HVDLlyHyNjuegogM4NA5z9+YRG9gA722H97AgOA/gSyf43zCIHdE899yuTIg3ciNXpm1jmImTDwdJPITI4RPhRugbvslbFKt2Vfr/6eTFb4W1WkY6m6YPdQjJr2tNZp3EQlko7BgXHRNz2LAc+gdwMq7IUf3R58ohtFgrbr6n7hDFWAlPr8f/T9I4CECU9/De+vgVQY5nxh4POEzybJeCTS5YnCNAZzhsRzkP1Bsmu4t4aYU07nYuerA6KWWcJYO6HHrKJjaE3Zl624UWz/QOOPjcWHc7QzdIk40yl5tCWjhIDhJX0xF4CBMvBsf10IF4Ac//Z/bPlsgAcOwn6S6n6CwxzUewLcRoYaKzV38M23i9o493CNwL6S1UUuaQe0QpvbUfdfiqglpcRccFU+nkWwambASUiVfLyqbg49xY2eyWh1hy/Sh37XjHpaIYKD7OUEfrgS5IC09MV/1gMBgKMDyH/n9N6AhhINfh7mdoMoIZt6r9fAh1cvfHXNya6N4DzDbqi8K5WWSYlmbbAdnkpV6FxJpWSo1V8DUmGb3rMRaQBG2JJgwN9wCDnNi8HNI3dKK1aG0dvHe/UciIJf6rt+Og5wgDn59X9P/xWAKQhxf2XweYH+FjB9suGVhIMlOnlo02GJhTOdc7vFyo/TQGxs2Li7lz9NwmPurBihnVi7WSWiwKvGYntOpJiOt5drKUKMkFnE8HLxNPmJ9NG4eP8mAYUv4Np8hhi3gdruSX+3CSWAwP38f8f6UoCuDPF+6Os8gnAbKnxQ3d2F0imydzDPKIuiN5lxu8EKkrFE82kftW2az1DbYImpMqTUW3FWIJ83r5hl2koJlla7+m0+PmSOZcjcdMgwS4g11iZ6qCLUg5jkxn0QFA6BWvOvfzEFBIBHAtp/Qfa3gC4RSH5y5yeD2B/8evnYS4cULgR2CMsUja47cG/QvW6UeEhXZ3+xP51GVNVdP6Zpp+1eDFM5nMeySWghR4+TNL85cD46YIyCzKJ2kCzEhoTabXtGHs+CCemJfpMPjoDe9+t/qQALgM8Gj3++8UaBqRV2fQTjO4Q3JKd5r9TgiEYyMHTxxiWPpz8jbfq585YpTJpk960xoKFXsVoTo7yq6GGMTw==\" type=\"audio/wav\" />\n",
       "                    Your browser does not support the audio element.\n",
       "                </audio>\n",
       "              "
      ],
      "text/plain": [
       "<IPython.lib.display.Audio object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#|eval: false\n",
    "#|hide\n",
    "from tsai.export import get_nb_name; nb_name = get_nb_name(locals())\n",
    "from tsai.imports import create_scripts; create_scripts(nb_name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "python3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
